import { isUndefined } from "./is";
import { tryRun } from "./tryRun";
declare const sync: any;
/**
 * 不是很精确的 超时
 */
export function doTimeoutMax(fn: Function, timeout: number = 3000) {
    const end_time = new Date().getTime() + timeout;
    const d = threads.disposable();
    let runing: boolean = true;
    const i = threads.start(() => {
        while (runing && (end_time > new Date().getTime())) {
            sleep(1000)
        }
        tryRun(() => runing && d.setAndNotify(false))
    });
    const t = threads.start(() => {
        try {
            sync(fn)();
            tryRun(() => runing && d.setAndNotify(true));
        } catch (e) {
            tryRun(() => runing && d.setAndNotify(false))
        }
    });
    t.waitFor();
    const res = d.blockedGet()
    runing = false;
    tryRun(() => i.interrupt());
    tryRun(() => t.interrupt());
    return res;
}

export function tryDoCount(task: Function, onSuccess: Function, onFail: Function, count: number = 1, onCutdown?: Function) {
    let res = task()
    while (isUndefined(res) && count > 1) {
        res = task()
        count -= 1;
        onCutdown && onCutdown(count)
        sleep(1000)
    }
    if (isUndefined(res)) {
        onFail()
    } else {
        onSuccess(res)
    }
}
export function tryDoTimeout(task: Function, onSuccess: Function, onFail: Function, timeout: number, onCutdown?: Function) {
    const d = threads.disposable()
    const timer = setTimeout(() => {
        d.setAndNotify(false);
    }, timeout)
    const thread = threads.start(() => {
        tryRun(() => task())
        d.setAndNotify(true)
    });
    let i = 0;
    const interval = setInterval(() => {
        i += 1;
        const decTime = Math.floor(timeout / 1000 - i);
        onCutdown && onCutdown(decTime)
    }, 1000);
    thread.waitFor();
    const res = d.blockedGet();
    tryRun(() => {
        thread && thread.isAlive() && thread.interrupt();
    })
    clearTimeout(timer)
    clearInterval(interval)
    if (res) return tryRun(() => onSuccess())
    return tryRun(() => onFail())
}
